"""
    Author:
    Date: 2018-10-30

    辅助类。
"""

import calendar
import datetime
import hashlib
import os
import string
import time
import random

from django.conf import settings
from django.http import StreamingHttpResponse
from xml.etree.ElementTree import fromstring

# ------------------------------------------------------------------------------
# django 相关
# ------------------------------------------------------------------------------


def get_request_real_ip(request):
    """ 获取请求的真实ip """
    if 'HTTP_X_FORWARDED_FOR' in request.META:
        ip_list = request.META['HTTP_X_FORWARDED_FOR']
    else:
        ip_list = request.META['REMOTE_ADDR']
    return [x.strip() for x in ip_list.split(',')]


def is_ios_device(request):
    """ 判断请求的设备是否是ios设备 """
    agent = request.META.get('HTTP_USER_AGENT', '').lower()
    key_words = ['iPhone', 'iPad', 'iPod']
    for word in key_words:
        if word.lower() in agent:
            return True
    return False


def download_file(file_path):
    """ 下载文件 """
    (file_dir, filename) = os.path.split(file_path)
    with open(file_path) as f:
        c = f.read()
        response = StreamingHttpResponse(c)
        response['Content-Type'] = 'application/octet-stream'
        # response['Content-Disposition'] = f'attachment;filename="{filename}"'
        return response


def is_weixin(request):
    """ 判断是否是微信浏览器 """
    agent = request.META.get('HTTP_USER_AGENT', '').lower()
    return 'micromessenger' in agent


def is_qq(request):
    """ 判断是否是QQ浏览器 """
    agent = request.META.get('HTTP_USER_AGENT', '').lower()
    return 'qq' in agent

# ------------------------------------------------------------------------------
# xml 相关
# ------------------------------------------------------------------------------


def xml_to_dict(xml):
    """ 将xml转为dict """
    dict_data = {}
    root = fromstring(xml)
    for child in root:
        value = child.text
        dict_data[child.tag] = value
    return dict_data


def dict_to_xml(dic, exclude_items=None, root='xml'):
    """ 将xml转为xml """
    if exclude_items is None:
        exclude_items = []

    ret = [f'<{root}>']
    for k, v in dic.items():
        if type(v) == int or (k in exclude_items):
            ret.append(f'<{k}>{v}</{k}>')
        else:
            ret.append(f'<{k}><![CDATA[{v}]]></{k}>')
    ret.append(f'</{root}>')
    xml_data = ''.join(ret)
    xml_data = xml_data.encode('utf-8')
    return xml_data


def dict_to_raw_xml(dic, root='xml'):
    """ 将xml转为xml """
    ret = [f'<{root}>']
    for k, v in dic.items():
        ret.append(f'<{k}>{v}</{k}>')
    ret.append(f'</{root}>')
    xml_data = ''.join(ret)
    xml_data = xml_data.encode('utf-8')
    return xml_data


# def dict_to_raw_xml2(params, cdata=True, encoding='utf-8'):
#     """ dict转xml """
#     tag = '<{0}><![CDATA[{1}]]></{0}>' if cdata else '<{0}>{1}</{0}>'
#     s = ''.join(tag.format(k, v) for k, v in params.items())
#     return '<xml>{}</xml>'.format(s).encode(encoding)

# def trans_dict_to_xml(data_dict):
#     data_xml = []
#     for k in sorted(data_dict.keys()):  # 遍历字典排序后的key
#         v = data_dict.get(k)  # 取出字典中key对应的value
#         if k == 'detail' and not v.startswith('<![CDATA['):  # 添加XML标记
#             v = '<![CDATA[{}]]>'.format(v)
#         data_xml.append('<{key}>{value}</{key}>'.format(key=k, value=v))
#     return '<xml>{}</xml>'.format(''.join(data_xml)).encode('utf-8')  # 返回XML，并转成utf-8，解决中文的问题


# ------------------------------------------------------------------------------
# 日期 & 时间
# ------------------------------------------------------------------------------


def now():
    return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')


def get_iso_week_number():
    """ 获取今天是今年的第几周 """
    return datetime.date.today().isocalendar()[1]


def get_first_day_of_this_month_timestamp():
    """ 获取本月第一天零点的timestamp """
    datetime_now = datetime.datetime.now()
    first_day_of_this_month = datetime.datetime(datetime_now.year, datetime_now.month, 1)
    return int(time.mktime(first_day_of_this_month.timetuple()))


def get_today_timestamp():
    """ 获取今日零点的timestamp """
    datetime_now = datetime.datetime.now()
    today = datetime.datetime(datetime_now.year, datetime_now.month, datetime_now.day, 0, 0, 0)
    return int(time.mktime(today.timetuple()))


def get_yesterday_timestamp():
    """ 获取昨日零点的timestamp """
    return get_today_timestamp() - 24 * 3600


def get_timestamp(year, month, day, hour=0, minute=0, second=0):
    """ 获取今日零点的timestamp """
    d = datetime.datetime(year, month, day, hour, minute, second)
    return int(time.mktime(d.timetuple()))


# def get_timestamp_from_str(s):
#     """ 将YYYY-MM-DD hh:mm:ss格式的时间转为时间戳 """
#     if ' ' in s:
#         p1, p2 = s.strip().split(' ')
#         year, month, day = p1.split('-')
#         hour, minute, second = p2.split(':')
#     else:
#         year, month, day = s.split('-')
#         hour, minute, second = 0, 0, 0
#     return get_timestamp(int(year), int(month), int(day), int(hour), int(minute), int(second))


# def format_timestamp(ts):
#     """ 格式化timestamp为字符串形式 """
#     return str(datetime.datetime.fromtimestamp(ts))


def get_seconds_desp(seconds):
    """ 获取时间的描述 """
    if seconds < 60:
        return f'{seconds}秒'
    elif seconds < 60*60:
        minute = int(seconds/60)
        second = seconds % 60
        return f'{minute}分{second}秒'
    elif seconds < 24*60*60:
        hour = int(seconds / 3600)
        seconds -= hour * 3600
        return f'{hour}小时{get_seconds_desp(seconds)}'
    else:
        day = int(seconds / (24 * 3600))
        seconds -= day * 24 * 3600
        return f'{day}天{get_seconds_desp(seconds)}'


def strtotime(s):
    """ 将YYYY-MM-DD hh:mm:ss格式的时间转为时间戳 """
    if ' ' in s:
        p1, p2 = s.strip().split(' ')
        year, month, day = p1.split('-')
        hour, minute, second = p2.split(':')
    else:
        year, month, day = s.split('-')
        hour, minute, second = 0, 0, 0
    return get_timestamp(int(year), int(month), int(day), int(hour), int(minute), int(float(second)))


def strtodatetime(s):
    """ 将YYYY-MM-DD hh:mm:ss格式的时间转为时间戳 """
    if ' ' in s:
        p1, p2 = s.strip().split(' ')
        year, month, day = p1.split('-')
        hour, minute, second = p2.split(':')
    else:
        year, month, day = s.split('-')
        hour, minute, second = 0, 0, 0
    return datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), int(float(second)))


def timetostr(ts):
    """ 格式化timestamp为字符串形式 """
    return str(datetime.datetime.fromtimestamp(ts))


def datetimetostr(dt, format_str="%Y-%m-%d %H:%M:%S"):
    """ 将DateTime对象转为字符串形式 """
    return dt.strftime(format_str)


def datetostr(dt):
    """ 将DateTime对象转为字符串形式 """
    return dt.strftime("%Y-%m-%d 00:00:00")


def datetimetotime(dt):
    """ 将DateTime对象转为时间戳 """
    return strtotime(datetimetostr(dt))


def get_last_weekday(weekday):
    """ 获取上一个指定的星期 """
    one_day = datetime.timedelta(days=1)
    temp = datetime.date.today() - one_day
    while temp.weekday() != weekday:
        temp -= one_day
    return temp


def get_tomorrow_str():
    """ 获取明天的datetime """
    one_day = datetime.timedelta(days=1)
    tomorrow = datetime.date.today() + one_day
    return datetimetostr(tomorrow)


def get_first_day_of_month(offset):
    """ 获取指定月份的第一天 """
    datetime_now = datetime.datetime.now()
    today = datetime.datetime(datetime_now.year, datetime_now.month, datetime_now.day, 0, 0, 0)

    today = datetime.date.today()
    first = today.replace(day=1)
    while offset > 0:
        offset -= 1
        temp = first - datetime.timedelta(days=1)
        first = temp.replace(day=1)
    return first


def get_today_interval():
    """ 返回今天的开始时间和结束时间 """
    begin = datetime.date.today()
    end = begin + datetime.timedelta(days=1)
    return datetimetostr(begin)[:10], datetimetostr(end)[:10]


def get_last_days_info(days, start_day=None):
    """ 获取最近几天的时间信息 """
    if start_day is None:
        start_day = datetime.date.today()
    else:
        start_day = strtodatetime(start_day)

    info = []
    begin = start_day + datetime.timedelta(days=1)
    for i in range(days):
        end = begin
        begin = begin - datetime.timedelta(days=1)
        batch = '%4d-%02d-%02d' % (begin.year, begin.month, begin.day)
        info.append((batch,  datetimetostr(begin), datetimetostr(end)))
    return info


def get_last_weeks_info(weeks):
    """ 获取最近几周的时间信息 """
    info = []
    begin = get_last_weekday(calendar.MONDAY)
    for i in range(weeks):
        end = begin + datetime.timedelta(days=7)
        batch = '%4d年%02d周' % (end.year, begin.isocalendar()[1])
        info.append((batch,  datetimetostr(begin), datetimetostr(end)))
        begin = begin - datetime.timedelta(days=7)
    return info


def get_last_months_info(months):
    """ 获取最近几月的时间信息 """
    info = []
    begin = get_first_day_of_month(0)
    for i in range(months):
        end = begin
        begin = get_first_day_of_month(i + 1)
        batch = '%4d年%02d月' % (begin.year, begin.month)
        info.append((batch,  datetimetostr(begin), datetimetostr(end)))
        begin = begin - datetime.timedelta(days=7)
    return info


def is_work_time():
    """ 判断当前是否是工作时间 """
    if settings.DEBUG:
        return True

    datetime_now = datetime.datetime.now()
    weekday = datetime_now.weekday()
    if weekday not in [0, 1, 2, 3, 4]:
        return False

    current_time = datetime_now.strftime('%H:%M:%S')
    if current_time < '09:00:00' or current_time >= '17:00:00':
        return False

    return True

# ------------------------------------------------------------------------------
# MD5
# ------------------------------------------------------------------------------


def file_md5(file_path):
    """ 计算文件的md5 """
    hash_md5 = hashlib.md5()
    with open(file_path, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()


# ------------------------------------------------------------------------------
# 其他
# ------------------------------------------------------------------------------

def parse_post_params(request, fields_meta_data):
    """ 解析POST的参数 """
    params = {}
    for field_name, field_type in fields_meta_data:
        if field_type == 'int':
            value = request.POST.get(field_name, '0').strip()
            try:
                value = int(float(value))
            except ValueError:
                value = 0
        elif field_type == 'checkbox':
            value = 0 if not request.POST.get(field_name, []) else 1
        else:
            value = request.POST.get(field_name, '').strip()
        params[field_name] = value
    return params


def random_str(length):
    """ 生成随机字符串"""
    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))


def is_url(text):
    """ 判断给定的字符串是否是url """
    if text.lower().startswith('http://'):
        return True

    if text.lower().startswith('https://'):
        return True

    return False


def is_image_url(text):
    """ 判断是否是图片url """
    text = text.lower()
    if not is_url(text):
        return False

    ext = text[text.rfind('.'):]
    if ext in ['.png', '.jpg', '.jpeg', '.gif']:
        return True

    if 'easemob.com' in text:
        return True

    return False


def cdn_url(url):
    """ 修改CDN url """
    if url is None:
        return ''

    url = url.replace('.papatv.net', '.mqnetswork.com')
    return url


# ------------------------------------------------------------------------------
if __name__ == '__main__':
    print('ok')
